/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package poker;

import java.io.Serializable;
import java.util.Vector;
import prop.Jugador;
/**
 *
 * @author Ivan
 */
public class Partida implements Serializable {

    //MODIFICADO POR REYES: hago public esta enumeración:
    public enum Estado {APUESTAS1,DESCARTES,APUESTAS2,FINALIZAR};
    private Estado estado = Estado.APUESTAS1;
    private int jugadorActual = 0;
    private int ultimoSubido = 0;
    private boolean inicio = true;
    private int apuesta = 0;
    private DriverDomainInterfaz interfaz;
    private Vector<Jugador> jugadores;
    private MesaPoker mesa;
    private SesionPoker sesion;

    public void setUltimoSubido(int i) {
        ultimoSubido = i;
    }

    private int numJugadores() {
        int i = 0;
        int sum = 0;
        int hum = 0;
        while(i < jugadores.size()) {
            JugadorPoker jugador = (JugadorPoker) jugadores.get(i);
            if (jugador.getEstado() == ManoPoker.Estado.JUGANDO) {
                ++sum;
                if(!jugador.getClass().getName().equals("poker.JugadorMaquinaPoker")) {
                    ++hum;
                }
            }
            ++i;
        }
        interfaz.setHumanos(hum);
        return sum;
    }

    private void actualizar_jugadores() {
        int i = 0;
        while(i < jugadores.size()) {
            JugadorPoker jugador = (JugadorPoker) jugadores.get(i);
            jugador.setDinero(jugador.getDinero()-jugador.getApuesta());
            mesa.setBote(mesa.getBote() + jugador.getApuesta());
            jugador.setApuesta(0);
            ++i;
        }
    }

    private void finaliza() {
        int i = 0;
        Vector<JugadorPoker> v = new Vector<JugadorPoker>();
        int max = 0;
        while(i < jugadores.size()) {
            JugadorPoker jugador = (JugadorPoker) jugadores.get(i);
            if(jugador.getEstado() != ManoPoker.Estado.RETIRADO) {
                int eval = jugador.getMano().evaluar();
                System.out.println(eval);
                if(eval > max) {
                    v.clear();
                    v.add(jugador);
                    max = eval;
                }
                else if(eval == max) v.add(jugador);
            }
            ++i;
        }
        i = 0;
        int ganado = mesa.getBote();
        while(i < v.size()) {
            JugadorPoker jugador = (JugadorPoker) v.get(i);
            jugador.setDinero(jugador.getDinero()+ganado);
            ++i;
        }
        mesa.setBote(0);
        i = 0;
        interfaz.getSistema().getDDR2().resetear();
        while(i < jugadores.size()) {
            JugadorPoker jugador = (JugadorPoker) jugadores.get(i);
            ManoPoker man = jugador.getMano();
            for (int j = 0; j < man.getNumCartas(); j++) {
                mesa.getBaraja().anadirCarta(man.quitarCarta(j));
            }
            interfaz.getSistema().getDDR2().insertar(jugador.getNombre(), jugador.getDinero());
            ++i;
        }
        interfaz.iniciarGanaPartida(v, ganado);
    }

    public void rank() {
        int i = 0;
        while(i < jugadores.size()) {
            JugadorPoker jugador = (JugadorPoker) jugadores.get(i);
            interfaz.getDDR().insertar(jugador.getNombre(), jugador.getDinero());
            ++i;
        }
    }

    private void log(boolean subido) {
            JugadorPoker j;
            if(estado != Estado.DESCARTES) {
                j = (JugadorPoker) jugadores.get(ultimoSubido);
                if(subido) interfaz.anadirLog(j.getNombre() +
                           " ha subido la apuesta a " + mesa.getApuesta());
                else if (!inicio){
                    j = (JugadorPoker) jugadores.get(jugadorActual-1);
                    if(j.getEstado() == ManoPoker.Estado.RETIRADO) {
                        interfaz.anadirLog(j.getNombre() + " se ha retirado");
                        interfaz.anadirLog("Quedan " + numJugadores() +" jugadores");
                    }
                    else {
                        interfaz.anadirLog(j.getNombre() + " mantiene la apuesta");
                    }
                }
            }
            else {
                if (!inicio){
                    j = (JugadorPoker) jugadores.get(jugadorActual-1);
                    interfaz.anadirLog(j.getNombre() + " ha descartado " +
                            j.getDescartado() + " cartas");
                    j.setDescartado(0);
                }
            }
    }

    //busca el proximo jugador que no este retirado, si llega al jugador que
    //haya subido la ultima apuesta para tambien.
    private void proximoJugando(){
            boolean subido = false;
            if(mesa.getApuesta() > apuesta && !inicio) {
                ultimoSubido = jugadorActual-1;
                apuesta = mesa.getApuesta();
                subido = true;
            }
            else if(inicio){
                apuesta = mesa.getApuesta();
            }
            JugadorPoker j;
            log(subido);
            if(jugadorActual == jugadores.size()) jugadorActual = 0;
            j = (JugadorPoker) jugadores.get(jugadorActual);
            while(j.getMano().getEstado() == ManoPoker.Estado.RETIRADO
                && jugadorActual != ultimoSubido &&  !inicio) {
                ++jugadorActual;
                if(jugadorActual == jugadores.size()) jugadorActual = 0;
                j = (JugadorPoker) jugadores.get(jugadorActual);
            }
    }

    private void limpiarRefs() {
        int i = 0;
        while(i < jugadores.size()) {
            if(jugadores.get(i).getClass().getName().equals("poker.JugadorMaquinaPoker")) {
                JugadorMaquinaPoker jugador = (JugadorMaquinaPoker) jugadores.get(i);
                jugador.setPartida(null);
            }
            ++i;
        }
    }

    //llama a la ventana del proximo jugador que le toque jugar
    public void seguir() {
        JugadorPoker j = null;
        if (estado == Estado.FINALIZAR) {
            limpiarRefs();
            sesion.finalizarPartida();
            return;
        }
        if(numJugadores() == 1 && estado != Estado.FINALIZAR) {
            log(false);
            actualizar_jugadores();
            finaliza();
            estado = Estado.FINALIZAR;
            mesa.setEstado(Estado.FINALIZAR);
            return;
        }
        if(estado == Estado.APUESTAS1) {
            proximoJugando();
            if(jugadorActual != ultimoSubido || inicio){
                j = (JugadorPoker) jugadores.get(jugadorActual);
                if(j.getClass().getName().equals("poker.JugadorMaquinaPoker")) {
                    JugadorMaquinaPoker j2 = (JugadorMaquinaPoker) j;
                    j2.pedirApuesta();
                }
                else {
                    interfaz.iniciarApuesta(j);
                }
                ++jugadorActual;
                inicio = false;
            }
            else {
                actualizar_jugadores();
                inicio = true;
                estado = Estado.DESCARTES;
                mesa.setEstado(Estado.DESCARTES);
            }
        }
        if(estado == Estado.DESCARTES) {
            proximoJugando();                    System.out.println("pido");
            if(jugadorActual != ultimoSubido || inicio){
                j = (JugadorPoker) jugadores.get(jugadorActual);
                if(j.getClass().getName().equals("poker.JugadorMaquinaPoker")) {
                    JugadorMaquinaPoker j2 = (JugadorMaquinaPoker) j;
                    j2.pedirDescarte();
                }
                else {
                    interfaz.iniciarDescarte(j);
                }
                ++jugadorActual;
                inicio = false;
            }
            else {

                inicio = true;
                estado = Estado.APUESTAS2;
                mesa.setEstado(Estado.APUESTAS2);
            }
        }
        if(estado == Estado.APUESTAS2) {
            proximoJugando();
            if(jugadorActual != ultimoSubido || inicio){
                j = (JugadorPoker) jugadores.get(jugadorActual);
                if(j.getClass().getName().equals("poker.JugadorMaquinaPoker")) {
                    JugadorMaquinaPoker j2 = (JugadorMaquinaPoker) j;
                    j2.pedirApuesta();

                }
                else {
                    interfaz.iniciarApuesta(j);
                }
                ++jugadorActual;
                inicio = false;
            }
            else {
                actualizar_jugadores();
                finaliza();
                estado = Estado.FINALIZAR;
                mesa.setEstado(Estado.FINALIZAR);
                return;
            }
        }

        if(j.getClass().getName().equals("poker.JugadorMaquinaPoker")) {
            this.seguir();
        }
    }

    //crea una nueva mesa y le da las cartas a los jugadores
    public Partida(DriverDomainInterfaz drv,MesaPoker mesa, SesionPoker sesion) {
        this.mesa = mesa;
        mesa.setApuesta(sesion.getConf().getInt("ApuestaInicial"));
        this.sesion = sesion;
        interfaz = drv;
        interfaz.setPartida(this);
        jugadores = mesa.getJugadores();
        interfaz.setMesa(mesa);
        int i = 0;
        while(i < jugadores.size()) {
            if(jugadores.get(i).getClass().getName().equals("poker.JugadorMaquinaPoker")) {
                JugadorMaquinaPoker jugador = (JugadorMaquinaPoker) jugadores.get(i);
                jugador.nuevaPartida();
                jugador.setMesa(mesa);
                jugador.setPartida(this);
            }
            else {
                JugadorPoker jugador = (JugadorPoker) jugadores.get(i);
                jugador.nuevaPartida();
            }
            ++i;
        }
        for(i = 0; i < 5; ++i) {
            int j = 0;
            while(j < jugadores.size()) {
                JugadorPoker jugador = (JugadorPoker) jugadores.get(j);
                jugador.getMano().anadirCarta(mesa.sacarCarta());
                ++j;
            }
        }
        mesa.setEstado(Estado.APUESTAS1);
        seguir();
    }

     //añadido por Reyes
    public MesaPoker getMesa(){
        return mesa;
        }
    public SesionPoker getSesion(){
        return sesion;
        }
    public Vector<Jugador> getJugadores(){
         return jugadores;
      }
    } //fin de la clase